package com.zzyang.aop.demo.interceptor;

import com.zzyang.aop.demo.interceptor.anno.AopInterceptor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * TODO
 *
 * @author zhuoziyang
 * @date 2021/5/17 0:17
 */
public class CglibHandler {

    private final Object target;

    public CglibHandler(Object target) {
        this.target = target;
    }

    public Object createProxyObject() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new AopInterceptorMethodInterceptor());
        return enhancer.create();
    }

    private class AopInterceptorMethodInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            AopInterceptor annotation = method.getAnnotation(AopInterceptor.class);
            if (annotation == null) {
                return method.invoke(CglibHandler.this.target, objects);
            }
            Class<? extends Interceptor> interceptorClass = annotation.interceptor();
            if (Interceptor.class.equals(interceptorClass)) {
                return method.invoke(CglibHandler.this.target, objects);
            }
            Interceptor interceptor = interceptorClass.newInstance();
            Invocation invocation = new Invocation();
            invocation.setProxy(o)
                    .setTarget(CglibHandler.this.target)
                    .setMethod(method)
                    .setArgs(objects);
            interceptor.before(invocation);
            Object retVal = invocation.proceed();
            return interceptor.after(invocation.setReturnValue(retVal));
        }
    }

}
